package cn.huiyunche.base.service.framework.utils;

import cn.huiyunche.tools.basic.exceptions.BusinessException;
import org.apache.commons.lang3.CharEncoding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 高德地图工具类
 *
 * @author houjianhui
 */
public class GDMapUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(GDMapUtils.class);

    private static final String KEY = "001950ab40ada48bb6fbc389ab70f2e8";

    private static final Pattern GPS_PATTERN = Pattern.compile("\"location\":\"(\\d+\\.\\d+),(\\d+\\.\\d+)\"");

    /**
     * 地址转经纬度
     *
     * @param address 地址
     * @return
     * @throws BusinessException
     */
    public static double[] addressToGPS(String address) throws Exception {
        String addressEncode = address;
        try {
            addressEncode = URLEncoder.encode(address, CharEncoding.UTF_8);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("addressToGPS encode error: {}", e);
            throw new BusinessException("地址编码错误");
        }
        LOGGER.info("addressToGPS addressStr:{} encoded: {}", address, addressEncode);
        String url = String.format("http://restapi.amap.com/v3/geocode/geo?address=%s&key=%s", addressEncode, KEY);
        URL myURL = null;
        URLConnection httpsConn = null;
        try {
            myURL = new URL(url);
        } catch (MalformedURLException e) {
            LOGGER.error("addressToGPS URL error: {}", e);
            throw new BusinessException("地址转GPS错误");
        }
        try {
            InputStreamReader insr = null;
            BufferedReader br = null;
            httpsConn = myURL.openConnection();// 不使用代理
            if (httpsConn != null) {
                insr = new InputStreamReader(httpsConn.getInputStream(), "UTF-8");
                br = new BufferedReader(insr);
                String data = "";
                String line = null;
                while ((line = br.readLine()) != null) {
                    data += line;
                }
                Matcher matcher = GPS_PATTERN.matcher(data);
                if (matcher.find() && matcher.groupCount() == 2) {
                    double[] gps = new double[2];
                    gps[0] = Double.valueOf(matcher.group(1));
                    gps[1] = Double.valueOf(matcher.group(2));
                    return gps;
                }
            }
        } catch (Exception e) {
            LOGGER.error("addressToGPS get error: {}", e);
            throw new BusinessException("获取地址经纬度错误");
        }
        return null;
    }


    /**
     * @param address 详细地址
     * @throws BusinessException
     * @Title: addressToGeocode
     * @Description: 根据详细地址信息返回地理编码
     * @return: double[]
     */
    public static double[] addressToGeocode(String address) throws Exception {
        String addressEncode = address;
        try {
            addressEncode = URLEncoder.encode(address, CharEncoding.UTF_8);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("addressToGeocode encode error: {}", e);
            throw new BusinessException("地址编码错误");
        }
        LOGGER.info("addressToGeocode addressStr:{} encoded: {}", address, addressEncode);
        String url = String.format("http://restapi.amap.com/v3/geocode/geo?address%s&key=%s", addressEncode, KEY);
        URL myURL = null;
        URLConnection httpsConn = null;
        try {
            myURL = new URL(url);
        } catch (MalformedURLException e) {
            LOGGER.error("addressToGPS URL error: {}", e);
            throw new BusinessException("地址转GPS错误");
        }
        try {
            InputStreamReader insr = null;
            BufferedReader br = null;
            httpsConn = myURL.openConnection();// 不使用代理
            if (httpsConn != null) {
                insr = new InputStreamReader(httpsConn.getInputStream(), "UTF-8");
                br = new BufferedReader(insr);
                String data = "";
                String line = null;
                while ((line = br.readLine()) != null) {
                    data += line;
                }
                Matcher matcher = GPS_PATTERN.matcher(data);
                if (matcher.find() && matcher.groupCount() == 2) {
                    double[] gps = new double[2];
                    gps[0] = Double.valueOf(matcher.group(1));
                    gps[1] = Double.valueOf(matcher.group(2));
                    return gps;
                }
            }
        } catch (Exception e) {
            LOGGER.error("addressToGPS get error: {}", e);
            throw new BusinessException("获取地址经纬度错误");
        }
        return null;
    }

    /**
     * 获取两地之间驾车导航距离
     *
     * @param origin      出发点（经度和纬度用","分隔）
     * @param destination 目的地 （经度和纬度用","分隔）
     * @param output      输出格式，默认JSON
     * @return
     */
    public static String distance(String origin, String destination, String output) {
        String url = String.format("http://restapi.amap.com/v3/distance?origins=%s&destination=%s&output=%s&key=%s&type=%s", origin, destination, output, KEY, 1);
        URL myURL = null;
        URLConnection httpsConn = null;
        try {
            myURL = new URL(url);
        } catch (MalformedURLException e) {
            LOGGER.error("distance URL error: {}", e);
            throw new BusinessException("获取地址经纬度错误");
        }
        try {
            InputStreamReader insr = null;
            BufferedReader br = null;
            httpsConn = myURL.openConnection();// 不使用代理
            if (httpsConn != null) {
                insr = new InputStreamReader(httpsConn.getInputStream(), "UTF-8");
                br = new BufferedReader(insr);
                String data = "";
                String line = null;
                while ((line = br.readLine()) != null) {
                    data += line;
                }
                return data;
            }
        } catch (Exception e) {
            LOGGER.error("distance get error: {}", e);
            throw new BusinessException("获取两地之间距离错误");
        }
        return null;
    }

    /**
     * 根据经纬度查询地理信息
     *
     * @param origin 经纬度（经度和纬度用","分隔）
     *               例如：（112.542904,37.77125）
     * @return
     */
    public static String distances(String origin) {
        String url = String.format("http://restapi.amap.com/v3/geocode/regeo?key=%s&location=%s&extensions=all&batch=false", KEY, origin);
        URL myURL = null;
        URLConnection httpsConn = null;
        try {
            myURL = new URL(url);
        } catch (MalformedURLException e) {
            LOGGER.error("distance URL error: {}", e);
            throw new BusinessException("获取地址经纬度错误");
        }
        try {
            InputStreamReader insr = null;
            BufferedReader br = null;
            httpsConn = myURL.openConnection();// 不使用代理
            if (httpsConn != null) {
                insr = new InputStreamReader(httpsConn.getInputStream(), "UTF-8");
                br = new BufferedReader(insr);
                String data = "";
                String line = null;
                while ((line = br.readLine()) != null) {
                    data += line;
                }
                return data;
            }
        } catch (Exception e) {
            LOGGER.error("distance get error: {}", e);
            throw new BusinessException("获取两地之间距离错误");
        }
        return null;
    }


    /**
     * 根据具体地址和城市定位区域
     *
     * @param address 具体地址（规则： 省+市+区+街道+门牌号）
     * @param city    查询城市（如：北京/beijing/010/110000）
     * @return
     */
    public static String county(String address, String city) {
        String url = String.format(" http://restapi.amap.com/v3/geocode/geo?key=%s&address=%s&city=%s", KEY, address, city);
        URL myURL = null;
        URLConnection httpsConn = null;
        try {
            myURL = new URL(url);
        } catch (MalformedURLException e) {
            LOGGER.error("distance URL error: {}", e);
            throw new BusinessException("查询地址错误");
        }
        try {
            InputStreamReader insr = null;
            BufferedReader br = null;
            httpsConn = myURL.openConnection();// 不使用代理
            if (httpsConn != null) {
                insr = new InputStreamReader(httpsConn.getInputStream(), "UTF-8");
                br = new BufferedReader(insr);
                String data = "";
                String line = null;
                while ((line = br.readLine()) != null) {
                    data += line;
                }
                return data;
            }
        } catch (Exception e) {
            LOGGER.error("distance get error: {}", e);
            throw new BusinessException("获取两地之间距离错误");
        }
        return null;
    }

    public static void main(String[] str) {
        county("北京市丰台区西四环中路83号", "北京市丰台区");
        double[] doStart = new double[0];
        double[] doEnd = new double[0];
        try {
            doStart = addressToGPS("北京市东城区");
            doEnd = addressToGPS("湖南省常德市市区");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(doStart[0] + "," + doStart[1]);
        System.out.println(doEnd[0] + "," + doEnd[1]);
        System.out.println(distance(doStart[0] + "," + doStart[1], doEnd[0] + "," + doEnd[1], "JSON"));
    }
}
